/**
  ******************************************************************************
  * @file           : studio_tcp.cpp
  * @author         : wangyingjie
  * @brief          : None
  * @attention      : None
  * @date           : 2025/7/1
  ******************************************************************************
  */

#include "studio_tcp_client.h"


void studio_tcp_client::stop()
{
    if (stopped_.exchange(true))
    {
        return;
    }

    std::cout << "Stopping TCP client...\n";

    // 使用 post 确保在 io_context 线程中执行
    asio::post(io_, [this]() {
        // 关闭 socket
        boost::system::error_code ec;
        socket_.close(ec);
        if (ec)
        {
            std::cout << "Socket close error: " << ec.message() << "\n";
        }

        // 取消定时器 - 使用无参 cancel()
        reconnect_timer_.cancel();  // 修正：无参调用

        // 停止 io_context
        io_.stop();
    });

    // 等待工作线程结束
    if (worker_thread_ && worker_thread_->joinable())
    {
        std::cout << "Waiting for worker thread to finish...\n";
        worker_thread_->join();
        worker_thread_.reset();
        std::cout << "Worker thread finished\n";
    }

    std::cout << "TCP client stopped successfully\n";
}

bool studio_tcp_client::send(const std::string& message)
{
    if (!connected_.load())
    {
        std::cout << "Not connected. Cannot send data.\n";
        return false;
    }
    std::lock_guard<std::mutex> lock(write_mutex_);
    // 将消息放入队列
    write_queue_.push(message);
    // 如果没有正在进行的写操作，启动写操作
    if (!write_in_progress_.load())
    {
        start_write();
    }
    return true;
}

void studio_tcp_client::connect()
{
    if (stopped_)
        return;

    std::cout << "Connecting to " << host_ << ":" << port_ << "...\n";

    auto endpoints = tcp::resolver(io_).resolve(host_, port_);
    asio::async_connect(socket_,
                        endpoints,
                        std::bind(&studio_tcp_client::on_connect, this, std::placeholders::_1, std::placeholders::_2));
}


void studio_tcp_client::on_connect(const boost::system::error_code& ec, const tcp::endpoint&)
{
    if (ec)
    {
        std::cout << "Connection failed, Retrying in seconds of " << RECONNECT_INTERVAL << "\n";
        // 使用 expires_after 替代 expires_from_now
        reconnect_timer_.expires_after(std::chrono::seconds(RECONNECT_INTERVAL));
        reconnect_timer_.async_wait(std::bind(&studio_tcp_client::on_reconnect_timer, this, std::placeholders::_1));
        return;
    }

    std::cout << "Connected successfully!\n";
    connected_.store(true);

    do_read();
}


void studio_tcp_client::do_read()
{
    if (stopped_)
    {
        return;
    }

    socket_.async_read_some(asio::buffer(buffer_),
                            std::bind(&studio_tcp_client::on_read, this, std::placeholders::_1, std::placeholders::_2));
}


void studio_tcp_client::on_read(const boost::system::error_code& ec, std::size_t bytes_transferred)
{
    if (ec)
    {
        std::cout << "Read error: " << ec.message() << "\n";
        connected_.store(false);
        disconnect_and_reconnect(std::chrono::seconds(1));
        return;
    }

    std::string data(buffer_.data(), bytes_transferred);
    if (msg_handler_)
    {
        msg_handler_(data);
    }

    do_read();
}


void studio_tcp_client::start_write()
{
    // 从队列中取出一条消息进行发送
    if (!write_queue_.empty())
    {
        std::string message = write_queue_.front();
        write_queue_.pop();
        asio::async_write(socket_,
                          asio::buffer(message),
                          std::bind(&studio_tcp_client::on_write, this, std::placeholders::_1, std::placeholders::_2));
        write_in_progress_.store(true);
    }
}


void studio_tcp_client::disconnect_and_reconnect(std::chrono::steady_clock::duration delay)
{
    // 使用新的 post 语法
    asio::post(io_, [this, delay]() {
        boost::system::error_code ec;
        socket_.close(ec);
        // 使用 expires_after 替代 expires_from_now
        reconnect_timer_.expires_after(delay);
        reconnect_timer_.async_wait(std::bind(&studio_tcp_client::on_reconnect_timer, this, std::placeholders::_1));
    });
}

